import 'dart:async';
import 'dart:convert';

import 'package:cached_network_image/cached_network_image.dart';
/**
 * 聊天
 * page聊天
 */
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:overlay_support/overlay_support.dart';
import 'package:provide/provide.dart';
import 'package:qgchat/common/class/date/index.dart';
import 'package:qgchat/common/class/sql/Sql.dart';
import 'package:qgchat/common/class/toUserInfo/toUserInfo.dart';
import 'package:qgchat/common/class/videoCall/index.dart';
import 'package:qgchat/common/global/global.dart';
import 'package:qgchat/http/apis/common.dart';
import 'package:qgchat/http/models/LocalTalkRecordModel.dart';
import 'package:qgchat/http/models/textModel.dart';
import 'package:qgchat/page/live/videoPage/giftBox.dart';
import 'package:qgchat/states/states_model/index.dart';
import 'package:qgchat/widgets/tipsDialog.dart';
import 'package:qgchat/widgets/emoji/emoji.dart';

import 'Bloc/ChatBloc.dart';

class Chat extends StatefulWidget {
  Chat(
    this.targetId,
    this.targetName,
    this.targetHead,
    this.targetToken, {
    Key key,
  }) : super(key: key);

  // 对方id
  final int targetId;
  // 对方昵称
  final String targetName;
  // 对方头像
  final String targetHead;
  // 对方token
  final String targetToken;

  @override
  _ChatState createState() => _ChatState();
}

class _ChatState extends State<Chat> {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => ChatBloc(
        targetId: widget.targetId,
        targetName: widget.targetName,
        targetHead: widget.targetHead,
        targetToken: widget.targetToken,
      ),
      child: Scaffold(
        backgroundColor: Colors.white,
        appBar: appbarHandle(),
        body: Column(
          children: <Widget>[
            // 聊天记录
            _TalkList(
              targetId: widget.targetId,
              targetName: widget.targetName,
              targetHead: widget.targetHead,
              targetToken: widget.targetToken,
            ),
            // 输入框
            _Footer(),
          ],
        ),
      ),
    );
  }

  // 生成appbar
  Widget appbarHandle() {
    UserState user = state(context, 'user');
    List<Widget> actions = [];

    actions.add(IconButton(
      padding: EdgeInsets.zero,
      onPressed: () {
        TipsDialog.report(context, () {
          toast('举报成功');
        });
      },
      icon: Text('举报'),
    ));

    if (widget.targetToken != Config.CUSTOMERSERVICESTAFF &&
        user.info.memberType == 0) {
      actions.add(IconButton(
        onPressed: () => TipsDialog.tryToVideo(
          context,
          widget.targetName,
          () => VideoCall.checkUserStatusAndGoVideoPage(
            context,
            widget.targetToken,
          ),
        ),
        icon: Image.asset(
          "assets/images/icon/videoCall.png",
          width: px(34),
          height: px(44),
        ),
      ));
    }

    return AppBar(
      centerTitle: true,
      actions: actions,
      title: Text(
        "${widget.targetName}",
        style: TextStyle(
          color: Colors.black,
          fontSize: px(34),
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  }
}

class _TalkList extends StatefulWidget {
  final int targetId;
  final String targetName;
  final String targetHead;
  final String targetToken;

  _TalkList({
    this.targetId,
    this.targetName,
    this.targetHead,
    this.targetToken,
    Key key,
  }) : super(key: key);

  @override
  __TalkListState createState() => __TalkListState();
}

class __TalkListState extends State<_TalkList> {
  ScrollController ctrl = ScrollController();

  List<LocalTalkRecordModel> list = [];

  /// 当前用户token
  String token;

  @override
  void initState() {
    super.initState();

    // socket监听消息
    final not = Global.socketNot;
    if (not.value != null) {
      not.value
          .map((str) => jsonDecode(str))
          .where((cls) => cls['datatype'] == 'message')
          .map(
            (cls) {
              final info = Provide.value<UserState>(context).info;
              return LocalTalkRecordModel.fromJson({
                "text": cls['data']['msg'],
                "member_nickname": cls['data']['name'],
                "member_head": cls['data']['head'],
                "from_id": cls['data']['token'],
                "to_id": info.memberToken,
              });
            },
          )
          .where((data) => data.fromId == widget.targetToken)
          .listen(
            (res) {
              list.add(res);
              setState(() {});
              Timer(
                Duration(milliseconds: 300),
                () {
                  ctrl.jumpTo(ctrl.position.maxScrollExtent);
                },
              );
            },
          );
    }

    context.bloc<ChatBloc>().listen((str) async {
      if (str.isEmpty) return;

      final info = Provide.value<UserState>(context).info;

      List<TextModel> textModel = await CommonApis.text(str);
      String status = textModel[0]?.results[0]?.label;
      Map textLabel = {
        // "normal": "",
        "spam": "含垃圾信息",
        "ad": "广告",
        "politics": "涉政",
        "terrorism": "暴恐",
        "abuse": "辱骂",
        "porn": "色情",
        "flood": "灌水",
        "contraband": "违禁",
        "meaningless": "无意义",
        "customized": "未知",
      };
      if (textModel.length > 0 && textLabel.containsKey(status)) {
        final data = LocalTalkRecordModel.fromJson({
          "text": '''$str\n
------------------
以上文字含有${textLabel[status]}类型敏感词\n
请重新编辑\n
          ''',
          "member_nickname": info.memberNickname,
          "member_head": info.memberHead,
          "from_id": info.memberToken,
          "to_id": widget.targetToken,
        });
        list.add(data);
      } else {
        Global.ws.sendMessage(widget.targetToken, str);

        final data = LocalTalkRecordModel.fromJson({
          "text": str,
          "member_nickname": info.memberNickname,
          "member_head": info.memberHead,
          "from_id": info.memberToken,
          "to_id": widget.targetToken,
        });
        list.add(data);
      }

      setState(() {});
      Timer(
        Duration(milliseconds: 300),
        () {
          ctrl.jumpTo(ctrl.position.maxScrollExtent);
        },
      );
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final info = Provide.value<UserState>(context).info;
    if (info?.memberToken == null) return;
    token = info.memberToken;

    // 加载数据库消息
    loadingData(info);
    // 同步线上数据
    // 同步完成后从新加载数据库消息
    Sql().synchronization(token).then((value) => loadingData(info));
  }

  loadingData(info) async {
    Sql().queryDialog(info.memberToken, widget.targetToken).then((arr) {
      if (!mounted) return;
      list = arr;
      setState(() {});
      Timer(
        Duration(milliseconds: 300),
        () {
          ctrl.jumpTo(ctrl.position.maxScrollExtent);
        },
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: GestureDetector(
        onTap: () {
          FocusScope.of(context).requestFocus(FocusNode());
          SystemChannels.textInput.invokeMethod('TextInput.hide');
        },
        child: SingleChildScrollView(
          controller: ctrl,
          child: Column(
            children: List.generate(
              list.length,
              (i) {
                final info = list[i];

                final iSay = _Isay(info.text);
                final heSay = _HeSay(
                  info.text,
                  token: widget.targetToken,
                  head: widget.targetHead,
                );
                if (i == 0) {
                  return token != info.toId ? iSay : heSay;
                } else {
                  final before = list[i - 1];
                  final isLongTime = before.createtime + 300 < info.createtime;
                  if (isLongTime) {
                    return Column(
                      children: [
                        Container(
                          height: px(65),
                          alignment: Alignment.center,
                          child: Text(
                            "${Date.simple(info.createtime, format: "y/m/d h:i")}",
                            style: TextStyle(
                              color: col("909399"),
                              fontSize: px(22),
                            ),
                          ),
                        ),
                        token != info.toId ? iSay : heSay,
                      ],
                    );
                  } else {
                    return token != info.toId ? iSay : heSay;
                  }
                }
              },
            ),
          ),
        ),
      ),
    );
  }
}

/// 我说
class _Isay extends StatelessWidget {
  final String say;
  const _Isay(this.say, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: px(30), vertical: px(20)),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          // 内容
          ConstrainedBox(
            constraints: BoxConstraints(
              minWidth: px(50),
              maxWidth: w100(context) - px(148),
            ),
            child: Container(
              decoration: BoxDecoration(
                color: col("f5f7fa"),
                borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(px(14)),
                  topRight: Radius.circular(px(14)),
                  bottomLeft: Radius.circular(px(14)),
                ),
              ),
              margin: EdgeInsets.only(left: px(88), right: px(36)),
              padding: EdgeInsets.symmetric(
                horizontal: px(28),
                vertical: px(22),
              ),
              child: Text(
                say,
                style: TextStyle(
                  color: col("303133"),
                  fontSize: px(32),
                ),
              ),
            ),
          ),
          // 头像
          GestureDetector(
            onTapUp: (v) {
              UserState user = state(context, 'user');
              ToUserInfo.show(context, user.info.memberToken);
            },
            child: Container(
              width: px(74),
              height: px(74),
              child: ClipOval(
                child: stateBuilder(context, 'user', (UserState user) {
                  return CachedNetworkImage(
                    imageUrl: "${user.info.memberHead}",
                    fit: BoxFit.cover,
                    errorWidget: (context, url, error) {
                      return Config.errorNetImage;
                    },
                  );
                }),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

/// 他说
class _HeSay extends StatelessWidget {
  final String token;
  final String head;
  final String say;
  const _HeSay(this.say, {this.token, this.head, Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: px(30), vertical: px(20)),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          // 头像
          GestureDetector(
            onTapUp: (v) {
              ToUserInfo.show(context, token);
            },
            child: Container(
              width: px(74),
              height: px(74),
              child: ClipOval(
                child: CachedNetworkImage(
                  imageUrl: "$head",
                  fit: BoxFit.cover,
                  errorWidget: (context, url, error) {
                    return Config.errorNetImage;
                  },
                ),
              ),
            ),
          ),
          ConstrainedBox(
            constraints: BoxConstraints(
              minWidth: px(50),
              maxWidth: w100(context) - px(148),
            ),
            child: Container(
              decoration: BoxDecoration(
                color: col("f5f7fa"),
                borderRadius: BorderRadius.only(
                  topRight: Radius.circular(px(14)),
                  bottomLeft: Radius.circular(px(14)),
                  bottomRight: Radius.circular(px(14)),
                ),
              ),
              margin: EdgeInsets.only(left: px(36), right: px(88)),
              padding: EdgeInsets.symmetric(
                horizontal: px(28),
                vertical: px(22),
              ),
              child: Text(
                say,
                style: TextStyle(
                  color: col("303133"),
                  fontSize: px(32),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _Footer extends StatefulWidget {
  _Footer({Key key}) : super(key: key);

  @override
  __FooterState createState() => __FooterState();
}

class __FooterState extends State<_Footer> {
  final TextEditingController ctrl = TextEditingController();
  bool showEmoji = false;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: showEmoji ? px(440) : px(103),
      decoration: BoxDecoration(
        border: Border(
          top: BorderSide(
            color: col("edeff2"),
            width: 1,
          ),
        ),
      ),
      child: Column(
        children: [
          _InputPanel(
            ctrl: ctrl,
            emojiFn: ([state]) {
              if (state != null) {
                showEmoji = state;
              } else {
                showEmoji = !showEmoji;
              }
              setState(() {});
            },
          ),
          if (showEmoji)
            Emoji.widget(
              context,
              (emoji) {
                final text = ctrl.text;
                ctrl.text = text + emoji;
                ctrl.selection = TextSelection.collapsed(
                  offset: ctrl.text.length,
                  affinity: TextAffinity.downstream,
                );
              },
            ),
        ],
      ),
    );
  }
}

class _InputPanel extends StatelessWidget {
  final Function([bool]) emojiFn;
  final TextEditingController ctrl;

  _InputPanel({this.emojiFn, this.ctrl, Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final targetToken = context.bloc<ChatBloc>().targetToken;
    final info = Provide.value<UserState>(context).info;
    final kefuToken = Config.CUSTOMERSERVICESTAFF;
    final heIsKefu = targetToken == kefuToken;
    final isAnchor = info.memberType == 1;
    return Container(
      height: px(100),
      padding: EdgeInsets.only(left: px(30)),
      decoration: BoxDecoration(
        border: Border(bottom: BorderSide(width: 1, color: col("edeff2"))),
      ),
      child: Row(
        children: <Widget>[
          if (!heIsKefu || !isAnchor)
            Container(
              width: px(58),
              height: px(58),
              child: FlatButton(
                onPressed: () {
                  showModalBottomSheet(
                    context: context,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(px(24)),
                        topRight: Radius.circular(px(24)),
                      ),
                    ),
                    builder: (BuildContext context) {
                      return GiftBox(token: targetToken);
                    },
                  );
                },
                padding: EdgeInsets.zero,
                child: Image.asset("assets/images/icon/gift_org.png"),
              ),
            ),
          Expanded(
            child: Container(
              margin: EdgeInsets.symmetric(horizontal: px(15)),
              child: CupertinoTextField(
                controller: ctrl,
                onSubmitted: (text) {
                  context.bloc<ChatBloc>().add(ChatEvent(ctrl.text));
                  ctrl.clear();
                },
                onTap: () {
                  emojiFn(false);
                },
                placeholder: "请输入消息...",
                decoration: BoxDecoration(border: null),
              ),
            ),
          ),
          Container(
            width: px(60),
            height: px(60),
            child: FlatButton(
              onPressed: () {
                emojiFn();
                FocusScope.of(context).requestFocus(FocusNode());
                SystemChannels.textInput.invokeMethod('TextInput.hide');
              },
              padding: EdgeInsets.zero,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(
                  sp(30),
                ),
              ),
              child: Image.asset(
                "assets/images/icon/smile.png",
                width: px(60),
                height: px(60),
              ),
            ),
          ),
          Container(
            width: 1,
            height: px(42),
            color: col("edeff2"),
            margin: EdgeInsets.only(left: px(20)),
          ),
          Container(
            width: px(120),
            child: FlatButton(
              onPressed: () {
                context.bloc<ChatBloc>().add(ChatEvent(ctrl.text));
                ctrl.clear();
              },
              padding: EdgeInsets.all(0),
              child: Text(
                "发送",
                style: TextStyle(
                  color: col("303133"),
                  fontSize: px(32),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
